<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>react | 学习笔记</title><meta name="author" content="lzoxun"><meta name="copyright" content="lzoxun"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="简介官网 声明式编程：（维护状态，根据状态改变更新熏染UI界面） UI&#x3D;f(state） 组件化开发： 开发依赖必须依赖三个包  react：包含react所有核心代码  包含react web 和 react-native所共同拥有的核心代码   react-dom：react 熏染在不同平台所需要的核心代码  针对web 和native所完成的事情不同 web端：reacte-dom">
<meta property="og:type" content="article">
<meta property="og:title" content="react">
<meta property="og:url" content="http://example.com/2023/07/22/web/react/react-docs/index.html">
<meta property="og:site_name" content="学习笔记">
<meta property="og:description" content="简介官网 声明式编程：（维护状态，根据状态改变更新熏染UI界面） UI&#x3D;f(state） 组件化开发： 开发依赖必须依赖三个包  react：包含react所有核心代码  包含react web 和 react-native所共同拥有的核心代码   react-dom：react 熏染在不同平台所需要的核心代码  针对web 和native所完成的事情不同 web端：reacte-dom">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png">
<meta property="article:published_time" content="2023-07-22T07:14:09.694Z">
<meta property="article:modified_time" content="2023-07-22T07:14:09.694Z">
<meta property="article:author" content="lzoxun">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="http://example.com/2023/07/22/web/react/react-docs/index.html"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox/fancybox.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = {
  root: '/',
  algolia: undefined,
  localSearch: {"path":"/search.xml","preload":true,"top_n_per_article":1,"unescape":true,"languages":{"hits_empty":"找不到您查询的内容：${query}","hits_stats":"共找到 ${hits} 篇文章"}},
  translate: {"defaultEncoding":2,"translateDelay":0,"msgToTraditionalChinese":"繁","msgToSimplifiedChinese":"簡"},
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '',
  dateSuffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: {"chs_to_cht":"你已切换为繁体","cht_to_chs":"你已切换为简体","day_to_night":"你已切换为深色模式","night_to_day":"你已切换为浅色模式","bgLight":"#49b1f5","bgDark":"#1f1f1f","position":"bottom-left"},
  source: {
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: true,
  isAnchor: false,
  percent: {
    toc: true,
    rightside: false,
  },
  autoDarkmode: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: 'react',
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2023-07-22 15:14:09'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
    win.getCSS = (url,id = false) => new Promise((resolve, reject) => {
      const link = document.createElement('link')
      link.rel = 'stylesheet'
      link.href = url
      if (id) link.id = id
      link.onerror = reject
      link.onload = link.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        link.onload = link.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(link)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          const now = new Date()
          const hour = now.getHours()
          const isNight = hour <= 6 || hour >= 18
          if (t === undefined) isNight ? activateDarkMode() : activateLightMode()
          else if (t === 'light') activateLightMode()
          else activateDarkMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
    const detectApple = () => {
      if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
        document.documentElement.classList.add('apple')
      }
    }
    detectApple()
    })(window)</script><meta name="generator" content="Hexo 6.3.0"></head><body><div id="loading-box"><div class="loading-left-bg"></div><div class="loading-right-bg"></div><div class="spinner-box"><div class="configure-border-1"><div class="configure-core"></div></div><div class="configure-border-2"><div class="configure-core"></div></div><div class="loading-word">加载中...</div></div></div><script>(()=>{
  const $loadingBox = document.getElementById('loading-box')
  const $body = document.body
  const preloader = {
    endLoading: () => {
      $body.style.overflow = ''
      $loadingBox.classList.add('loaded')
    },
    initLoading: () => {
      $body.style.overflow = 'hidden'
      $loadingBox.classList.remove('loaded')
    }
  }

  preloader.initLoading()
  window.addEventListener('load',() => { preloader.endLoading() })

  if (false) {
    document.addEventListener('pjax:send', () => { preloader.initLoading() })
    document.addEventListener('pjax:complete', () => { preloader.endLoading() })
  }
})()</script><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src= "" data-lazy-src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">108</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">1</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><hr class="custom-hr"/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header"><nav id="nav"><span id="blog-info"><a href="/" title="学习笔记"><span class="site-name">学习笔记</span></a></span><div id="menus"><div id="search-button"><a class="site-page social-icon search" href="javascript:void(0);"><i class="fas fa-search fa-fw"></i><span> 搜索</span></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div></div><div id="toggle-menu"><a class="site-page" href="javascript:void(0);"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">react</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2023-07-22T07:14:09.694Z" title="发表于 2023-07-22 15:14:09">2023-07-22</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2023-07-22T07:14:09.694Z" title="更新于 2023-07-22 15:14:09">2023-07-22</time></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="react"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"><i class="fa-solid fa-spinner fa-spin"></i></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h3 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h3><p><a target="_blank" rel="noopener" href="https://zh-hans.reactjs.org/">官网</a></p>
<p>声明式编程：（维护状态，根据状态改变更新熏染UI界面） UI&#x3D;f(state）</p>
<p>组件化开发：</p>
<h4 id="开发依赖"><a href="#开发依赖" class="headerlink" title="开发依赖"></a>开发依赖</h4><p>必须依赖三个包</p>
<ul>
<li><p><strong>react</strong>：包含<code>react</code>所有核心代码</p>
<ul>
<li>包含<code>react web</code> 和 <code>react-native</code>所共同拥有的核心代码</li>
</ul>
</li>
<li><p><strong>react-dom</strong>：<code>react</code> 熏染在不同平台所需要的核心代码</p>
<ul>
<li>针对<code>web</code> 和<code>native</code>所完成的事情不同</li>
<li>web端：<code>reacte-dom</code>会将<code>jsx</code>最终渲染成真是DOM,显示在浏览器中</li>
<li>native端：<code>react-dom</code> 会将<code>jsx</code>最终渲染成原生控件</li>
</ul>
</li>
<li><p><strong>babel</strong>：将jsx转换成React代码的工具</p>
</li>
</ul>
<hr>
<h4 id="对比vue"><a href="#对比vue" class="headerlink" title="对比vue"></a>对比vue</h4><p>react：用户手动 setState 的时候 去重新执行 render 函数</p>
<p>vue：data数据改变直接劫持重新渲染模板</p>
<h3 id="组件"><a href="#组件" class="headerlink" title="组件"></a>组件</h3><p>将页面<strong>拆分</strong>为无数个<strong>小的组件</strong>，每个组件完成自己的<strong>独立功能</strong>，<strong>方便</strong>页面的<strong>关联</strong>与<strong>维护</strong> 与 <strong>复用</strong></p>
<p>每个<strong>单页面</strong>应用就是一棵<strong>组件树</strong>，么个组件都将 <strong>state 数据</strong> 、<strong>方法</strong>、<strong>render</strong> 关联起来</p>
<p>组件类型，前面的<strong>注重UI</strong>， 后面的<strong>注重逻辑</strong></p>
<blockquote>
<p>  根据组件<strong>定义方式</strong>：**函数组件 **和 <strong>类组件</strong></p>
</blockquote>
<blockquote>
<p>  根据内部是否有<strong>状态需要维护</strong>：<strong>无状态组件</strong> 和 <strong>有状态组件</strong></p>
</blockquote>
<blockquote>
<p>  根据组件<strong>职责</strong>：<strong>展示型 组件</strong> 和 <strong>容器型组件</strong></p>
</blockquote>
<h4 id="类组件-rpce"><a href="#类组件-rpce" class="headerlink" title="类组件 rpce"></a>类组件 rpce</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 1、组件名称必须大写开头  </span><br><span class="line"> * 2、类组件必须继承 React.Component</span><br><span class="line"> * 3、必须实现 render，也是唯一必须实现的</span><br><span class="line"> *</span><br><span class="line"> */</span><br><span class="line">class App extends React.Component &#123;</span><br><span class="line">    constructor() &#123;</span><br><span class="line">        super();</span><br><span class="line">        // 组件数据，this.state 固定的，不能改变</span><br><span class="line">        this.state = &#123;</span><br><span class="line">            message: &quot;Hello World&quot;</span><br><span class="line">        &#125;;</span><br><span class="line"></span><br><span class="line">        // 对需要绑定的方法, 提前绑定好this，class下默认绑定的this是undefined，箭头函数就不需要了</span><br><span class="line">        this.btnClick = this.btnClick.bind(this);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    // 组件方法(实例方法)</span><br><span class="line">    btnClick() &#123;</span><br><span class="line">        // setState 是 React.Component 继承的方法  </span><br><span class="line">        // 内部完成了两件事情:</span><br><span class="line">        // 1.将state中message值修改掉 2.自动重新执行render函数函数</span><br><span class="line">        // 2.应用类型建议不要直接该，向浅拷贝，改完，再重新全部复制过去，改变引用</span><br><span class="line">        this.setState(&#123;</span><br><span class="line">            message: &quot;Hello React&quot;,</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     *  渲染内容 render方法，名称固定 不能改变</span><br><span class="line">     *  可以返回react元素、数组|字符串|数值、fragments(高级)、Portals(高级)</span><br><span class="line">     */</span><br><span class="line">    render() &#123; // 里面的this 都是正常指向组件的this</span><br><span class="line">        return (</span><br><span class="line">            &lt;div&gt;</span><br><span class="line">                &lt;h2&gt;&#123;this.state.message&#125;&lt;/h2&gt;</span><br><span class="line">                &#123;/* 拿到 btnClick 指针，存到这里，没有调用，当用户点击才调用，所以默认拿不到this的*/&#125;</span><br><span class="line">                &lt;button onClick=&#123;this.btnClick&#125;&gt;修改文本&lt;/button&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">// this绑定的问题</span><br><span class="line">// const app = new App()</span><br><span class="line">// const foo = app.btnClick</span><br><span class="line">// foo(); // 默认绑定 =&gt; window =&gt; 严格模式下 =&gt; undefined  (babel 转换的和class里默认都是严格模式)</span><br><span class="line"></span><br><span class="line">// function bar() &#123;</span><br><span class="line">//   console.log(&quot;bar:&quot;, this);</span><br><span class="line">// &#125;</span><br><span class="line">// bar()</span><br><span class="line"></span><br><span class="line">// 将组件渲染到界面上</span><br><span class="line">const root = ReactDOM.createRoot(document.querySelector(&quot;#root&quot;));</span><br><span class="line">// App根组件</span><br><span class="line">root.render(&lt;App /&gt;);</span><br></pre></td></tr></table></figure>

<h5 id="生命周期"><a href="#生命周期" class="headerlink" title="生命周期"></a>生命周期</h5><p>生命周期就是事物从<strong>创建</strong>到<strong>销毁</strong>的过程，了解生命周期，可以让我们在<strong>适合的地方</strong>做想<strong>要做的事情</strong></p>
<p>生命周期 和 生命周期函数的关系</p>
<ul>
<li>整个生命周期有很多个阶段，react可以使<strong>程序</strong>走到<strong>指定阶段</strong>时<strong>自动触发</strong>（回调）相应的<strong>生命周期函数</strong><ul>
<li>装载阶段（Mount），组件第一层在DOM树种被渲染的过程，组件<strong>挂载到DOM</strong>上就会触发<code>componentDidMount</code></li>
<li>更新阶段 (Update) , 组件状态发生变化，重新渲染的过程，组件<strong>状态发生更新</strong>触发 <code>componentDidUpdate</code></li>
<li>卸载阶段（Unmount），组件从DOM树中被移除的过程，就叫<strong>即将移除</strong>触发 <code>componentWillUnmount</code></li>
</ul>
</li>
</ul>
<p>react 生命周期的过程</p>
<p><img src= "" data-lazy-src="/../../../static/img/react-live.jpg"></p>
<ul>
<li><p>Mounting 挂载阶段</p>
<ul>
<li><p><strong>constructor</strong>：创建组件实例 第一个执行 构造方法constructor </p>
<ul>
<li>组件 都是一个类，每使用移除 <HelloX/> 都会创建一个类的实例出来</li>
</ul>
</li>
<li><p><strong>render</strong>：第二个执行render方法渲染 </p>
<ul>
<li><strong>render 完成</strong> React 更新<strong>DOM</strong> 和 <strong>Refs</strong></li>
</ul>
</li>
<li><p><strong>componentDidMount</strong>：进行挂载到DOM上，挂载好就会 触发 <strong>第一个生命周期函数</strong></p>
<ul>
<li>依赖dom的操作</li>
<li>网络请求操作</li>
<li>处理一些订阅</li>
</ul>
</li>
</ul>
</li>
<li><p>更新状态阶段</p>
<ul>
<li><strong>setState</strong>：修改状态，修改完成之后<strong>又执行 render</strong> 重新 更新<strong>DOM</strong> 和 <strong>Refs</strong></li>
<li><strong>componentDidUpdate</strong>：更新完成，触发<strong>第二个生命周期函数</strong></li>
</ul>
</li>
<li><p>卸载阶段</p>
<ul>
<li><strong>componentWillUnmount</strong>：将组件从DOM树中移除之后触发 <strong>第三个生命周期函数</strong><ul>
<li>取消一些订阅，清理操作</li>
</ul>
</li>
</ul>
</li>
<li><p>不常用的生命周期</p>
<ul>
<li><strong>shouldComponentUpdate</strong>：处于 <strong>setDate 到 render 之间</strong>，如果返回<strong>false</strong>，说明<strong>不需要重新渲染</strong>界面 </li>
<li><strong>getSnapshotBeforeUpdate</strong>：处于 <strong>render 到 更新DOM 之间</strong>，获取或保存一写DOM更新前的一些信息</li>
</ul>
</li>
</ul>
<h4 id="函数组件-rfce，rmc"><a href="#函数组件-rfce，rmc" class="headerlink" title="函数组件  rfce，rmc"></a>函数组件  rfce，rmc</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 与类组件的差异（不包含hook）</span><br><span class="line"> *     没有生命周期，没有生命周期函数，也会被更新并挂载</span><br><span class="line"> *     this 关键字不能指向组件实例</span><br><span class="line"> *     内部没有状态 state,</span><br><span class="line"> * 函数组件存在的缺陷</span><br><span class="line"> * 		修改message之后，函数组件不知道自己要重新渲染</span><br><span class="line"> *      如果页面重新渲染，函数被重新执行，又会重新改变message</span><br><span class="line"> *      Hook 的出现时函数组件解决了没有state，没有生命周期等问题</span><br><span class="line"> */</span><br><span class="line">function App(props)&#123;</span><br><span class="line">    let message = &quot;lzoxun&quot;</span><br><span class="line">    // return 的东西与类组件的一致</span><br><span class="line">    return &lt;h1&gt;react元素 &#123;message&#125;&lt;/h1&gt;</span><br><span class="line">&#125;</span><br><span class="line">export default App</span><br></pre></td></tr></table></figure>

<h4 id="组件通信"><a href="#组件通信" class="headerlink" title="组件通信"></a>组件通信</h4><h5 id="父子通信（props-由父到子）"><a href="#父子通信（props-由父到子）" class="headerlink" title="父子通信（props 由父到子）"></a>父子通信（props 由父到子）</h5><blockquote>
<p>  组件存在<strong>嵌套关系</strong>，<strong>嵌进来</strong>的组件称为<strong>子组件</strong>  </p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line">// App.js</span><br><span class="line">import React from &#x27;react&#x27;</span><br><span class="line">import Headers from &quot;./components/Headers&quot;</span><br><span class="line">class App extends React.Component &#123;</span><br><span class="line">    constructor() &#123;</span><br><span class="line">        super();</span><br><span class="line">        this.state = &#123;</span><br><span class="line">            title: &#x27;首页&#x27;,</span><br><span class="line">            list: [1, 2, 3, 4, 5],</span><br><span class="line">            infos: &#123;</span><br><span class="line">                name: &#x27;lzo&#x27;,</span><br><span class="line">                height: &quot;380cm&quot;</span><br><span class="line">            &#125;,</span><br><span class="line"></span><br><span class="line">            count: 0,</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    changeCount(num) &#123;</span><br><span class="line">        this.setState(&#123;</span><br><span class="line">            count: this.state.count + num</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    render() &#123;</span><br><span class="line">        return (</span><br><span class="line">            &lt;div&gt;</span><br><span class="line">                &#123;/* 父传子：向子组件传入一个title等数据 */&#125;</span><br><span class="line">                &#123;/* 子传父：向子组件传入回调，接收子组件发送的数据 childExec*/&#125;</span><br><span class="line">                &lt;Headers</span><br><span class="line">                    title=&#123;this.state.title&#125;</span><br><span class="line">                    infos=&#123;this.state.infos&#125;</span><br><span class="line">                    list=&#123;this.state.list&#125;</span><br><span class="line">                    childExec=&#123;(num) =&gt; this.changeCount(num)&#125;</span><br><span class="line">                    slotele=&#123;&lt;div&gt;传入React元素实现插槽&lt;/div&gt;&#125;</span><br><span class="line">                    sloteleArea=&#123;(text) =&gt; &lt;div&gt;&#123;text&#125;&lt;/div&gt;&#125;</span><br><span class="line">                &gt;</span><br><span class="line">                    &lt;div className=&#x27;children-1&#x27;&gt;通过子元素实现插槽效果&lt;/div&gt;</span><br><span class="line">                    &lt;div className=&#x27;children-2&#x27;&gt;通过 this.props.children 获取组件间的子元素&lt;/div&gt;</span><br><span class="line">                &lt;/Headers&gt;</span><br><span class="line">                &lt;div&gt;&#123;this.state.count&#125;&lt;/div&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">export default App;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line">/* App.js  =&gt;  Headers.js */</span><br><span class="line">import React from &quot;react&quot;; // imr</span><br><span class="line">import PropTypes from &#x27;prop-types&#x27; // impt 用来限制props数据类型</span><br><span class="line"></span><br><span class="line">class Headers extends React.Component &#123;</span><br><span class="line">    constructor(props) &#123;</span><br><span class="line">        // props 接收父组件传入的所有数据</span><br><span class="line">        super(props);</span><br><span class="line">        this.state = &#123;&#125;;</span><br><span class="line"></span><br><span class="line">        console.log(this.props); // 可以直接使用</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    changeData() &#123;</span><br><span class="line">        this.props.childExec(3)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    render() &#123;</span><br><span class="line">        return (</span><br><span class="line">            &lt;div&gt;</span><br><span class="line">                &lt;div&gt;父传子 =》 &#123;this.props.title&#125;&lt;/div&gt;</span><br><span class="line">                &lt;div&gt;子传父 =》 &lt;button onClick=&#123;e =&gt; this.changeData()&#125;&gt;+3&lt;/button&gt;&lt;/div&gt;</span><br><span class="line">                &lt;div className=&quot;slot&quot;&gt;</span><br><span class="line">                    &lt;span className=&quot;left&quot;&gt;子元素的使用 =》 left&lt;/span&gt;</span><br><span class="line">                        &#123;this.props.children[0]&#125; &#123;/* 弊端就是需要多个子元素的话，所有都在列表，位置无法固定 */&#125;</span><br><span class="line">                        &#123;this.props.slotele&#125;</span><br><span class="line">                        &#123;this.props.sloteleArea(&#x27;作用域插槽，内容自定&#x27;)&#125;</span><br><span class="line">                    &lt;span className=&quot;right&quot;&gt;right&lt;/span&gt;</span><br><span class="line">                &lt;/div&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">// 如果需要限制类型的话，也可以用ts</span><br><span class="line">Headers.propTypes = &#123;</span><br><span class="line">    title: PropTypes.string.isRequired, // 字符串类型，并且必传</span><br><span class="line">    infos: PropTypes.object,</span><br><span class="line">    list: PropTypes.array,</span><br><span class="line">    slotele: PropTypes.element</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">// 设置默认值 </span><br><span class="line">Headers.defaultProps = &#123;</span><br><span class="line">    list: [],</span><br><span class="line">    infos: &#123;&#125;,</span><br><span class="line">    slotele:&lt;div&gt;默认&lt;/div&gt;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">export default Headers;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h5 id="非父子隔层通信"><a href="#非父子隔层通信" class="headerlink" title="非父子隔层通信"></a>非父子隔层通信</h5><blockquote>
<p>  官方提供的 Context ，数据共享，后期可以用redux代替</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/* App.js  =&gt;  HeadersChild.js */</span><br></pre></td></tr></table></figure>

<blockquote>
<p>  EventBus 事件总线，可以监听触发事件传值</p>
</blockquote>
<h4 id="setState-详细使用"><a href="#setState-详细使用" class="headerlink" title="setState 详细使用"></a>setState 详细使用</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line">/* 1、基本用法 */</span><br><span class="line">this.setState(&#123;</span><br><span class="line">	message: &quot;hello word&quot;</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">/* 2、回调函数 */</span><br><span class="line">this.setState((state,props)=&gt;&#123;</span><br><span class="line">    // 可以先处理 state,props</span><br><span class="line">    return &#123;</span><br><span class="line">        message: &quot;hello word&quot;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">/** </span><br><span class="line"> * 3、setState 在 react 事件处理中默认是异步调用 </span><br><span class="line"> *    - 异步可以提升性能，获取同一阶段 多个setState改变，批量更新</span><br><span class="line"> *    - 如果是同步的，setState 后，render 还没有执行，state和要给子组件的props不能保存同步</span><br><span class="line"> *    - </span><br><span class="line"> *    - 第二个参数回调中可以拿到最终结果</span><br><span class="line"> */</span><br><span class="line"></span><br><span class="line">this.setState(&#123;</span><br><span class="line">	message: &quot;hello word&quot;</span><br><span class="line">&#125;,()=&gt;&#123;</span><br><span class="line">     console.log(&quot;++++++:&quot;, this.state.message) // 拿到更新后的数据</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">/* 4、react 18 之前的同步做法，不是React事件的回调就能同步，之后全部setState做法都是异步的 */</span><br><span class="line"> setTimeout(() =&gt; &#123;</span><br><span class="line">     // 在react18之前, setTimeout中setState操作, 是同步操作</span><br><span class="line">     // 在react18之后, setTimeout中setState异步操作(批处理)</span><br><span class="line">     this.setState(&#123; message: &quot;hello word 111&quot; &#125;)</span><br><span class="line">     console.log(this.state.message)</span><br><span class="line"> &#125;, 0);</span><br><span class="line"></span><br><span class="line">/* 5、偏要实现同步效果，使用官方的 flushSync*/</span><br><span class="line">import &#123; flushSync &#125; from &#x27;react-dom&#x27;</span><br><span class="line">flushSync(() =&gt; &#123;</span><br><span class="line">    this.setState(&#123; message: &quot;你好啊, 李银河&quot; &#125;)</span><br><span class="line">&#125;)</span><br><span class="line">console.log(this.state.message) // 设置后先执行render，再执行这里</span><br></pre></td></tr></table></figure>

<blockquote>
<p>  数据不可变</p>
</blockquote>
<p>应用 类型数据不要去直接修改，如果有变化，解构出来，改好直接，全部替换过去，否则 <strong>PuerComponent</strong> 类组件里不会生效</p>
<h4 id="优化"><a href="#优化" class="headerlink" title="优化"></a>优化</h4><h5 id="更新机制"><a href="#更新机制" class="headerlink" title="更新机制"></a>更新机制</h5><p><img src= "" data-lazy-src="/../../../static/img/2022-12-19_075525.jpg"></p>
<ul>
<li>通过唯一的、不变的key对比新旧DOM树，尽量复用</li>
<li>dom树中不会跨层比较</li>
</ul>
<h5 id="shouldComponentUpdate-（SCU）"><a href="#shouldComponentUpdate-（SCU）" class="headerlink" title="shouldComponentUpdate （SCU）"></a>shouldComponentUpdate （SCU）</h5><ul>
<li><p>阻止 render 函数被随意执行</p>
</li>
<li><p>父组件 <strong>setState</strong> 被调用，即使<strong>数据没变</strong>， <strong>render函数</strong>会被<strong>重新执行</strong>，<strong>所有子组件</strong>都会重新渲染</p>
</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line">/* 原理通过生命周期 shouldComponentUpdate(nexeProps,newState) SCU拦截优化*/</span><br><span class="line">shouldComponentUpdate(newProps,newState)&#123;</span><br><span class="line">    if(this.state.message != newState.message)&#123;</span><br><span class="line">        return true</span><br><span class="line">    &#125;</span><br><span class="line">    return false</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/* 子组件 拦截*/</span><br><span class="line">shouldComponentUpdate(newProps,newState)&#123;</span><br><span class="line">    if(this.props.message != newProps.message)&#123;</span><br><span class="line">        return true</span><br><span class="line">    &#125;</span><br><span class="line">    return false</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/* 上面太繁琐，react提供的解决方案 */</span><br><span class="line"></span><br><span class="line">/* 类组件 Component 换成 PuerComponent 帮做我们浅层比较上面的朝操作*/</span><br><span class="line">import React from &#x27;react&#x27;</span><br><span class="line">import Headers from &quot;./components/Headers&quot;</span><br><span class="line">class App extends React.PuerComponent &#123;</span><br><span class="line">    constructor() &#123;</span><br><span class="line">        super();</span><br><span class="line">        this.state = &#123;&#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    render() &#123;</span><br><span class="line">        return (</span><br><span class="line">            &lt;div&gt;&lt;/div&gt;</span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">export default App;</span><br><span class="line"></span><br><span class="line">/* 函数组件 通过memo处理上面的问题*/</span><br><span class="line">/* 正常情况下，通过memo包裹的组件，只有props发生改变，组件才会重新渲染 */</span><br><span class="line">const PropFile = memo(function(props)&#123;</span><br><span class="line">    return &lt;h2&gt;&#123;prop.message&#125;&lt;/h2&gt;   </span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<h5 id="React-Refs-获取-dom"><a href="#React-Refs-获取-dom" class="headerlink" title="React Refs 获取 dom"></a>React Refs 获取 dom</h5><blockquote>
<p>  ref</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line">import React, &#123; createRef, forwardRef &#125; from &#x27;react&#x27;</span><br><span class="line">import Headers from &quot;./components/Headers&quot;</span><br><span class="line"></span><br><span class="line">// 通过 forwardRef 定义一个函数组件</span><br><span class="line">const Headers2 = forwardRef(function(props,ref)&#123;</span><br><span class="line">    retrun (</span><br><span class="line">        &lt;h1 ref=&#123;ref&#125;&gt;Headers2 h1&lt;/h1&gt;</span><br><span class="line">    )</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">class App extends React.PuerComponent &#123;</span><br><span class="line">    constructor() &#123;</span><br><span class="line">        super();</span><br><span class="line">        this.state = &#123;&#125;</span><br><span class="line">        </span><br><span class="line">        this.titleRef = createRef();</span><br><span class="line">        this.titleEl = null;</span><br><span class="line">        this.headRef = createRef();</span><br><span class="line">        this.headRef2 = createRef();</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    getNatDom()&#123;</span><br><span class="line">        // 1、直接获取</span><br><span class="line">        console.log(this.refs.lzo);</span><br><span class="line">        </span><br><span class="line">        // 2、提前创建好ref对象，绑定到元素上</span><br><span class="line">        console.log(this.titleRef.current)</span><br><span class="line">        </span><br><span class="line">        // 3、通过回调得到元素 赋值给 this.titleEl</span><br><span class="line">        console.log(this.titleEl)</span><br><span class="line">        </span><br><span class="line">        // 4、类组件：通过 ref 获取，函数组件没有实例所有无法获取</span><br><span class="line">        console.log(this.headRef.current) </span><br><span class="line">        </span><br><span class="line">        // 5、函数组件，需要forwardRef,拿到 里面的某个节点，如 h1</span><br><span class="line">        console.log(this.headRef2.current) // 得到 &lt;h1&gt;Headers2 h1&lt;/h1&gt;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    render() &#123;</span><br><span class="line">        return (</span><br><span class="line">            &lt;div ref=&#x27;lzo&#x27;&gt;1&lt;/div&gt;</span><br><span class="line">            &lt;div ref=&#123;this.titleRef&#125;&gt;2&lt;/div&gt;</span><br><span class="line">            &lt;div ref=&#123;el =&gt; this.titleEl = el&#125;&gt;3&lt;/div&gt;</span><br><span class="line">            &lt;Headers ref=&#123;this.headRef&#125;/&gt;</span><br><span class="line">            &lt;Headers2 ref=&#123;this.headRef2&#125;/&gt;</span><br><span class="line">            &lt;button onClick=&#123;e =&gt; this.getNatDom()&#125;&gt;&lt;/button&gt;</span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">export default App;</span><br></pre></td></tr></table></figure>

<h5 id="受控组件与非受控组件"><a href="#受控组件与非受控组件" class="headerlink" title="受控组件与非受控组件"></a>受控组件与非受控组件</h5><blockquote>
<p>  react 没有双向搬到，当表单元素绑定 value属性后就变成了 <strong>受控组件</strong>，值交给react控制</p>
<p>  受控组件是<strong>无法输入</strong>的，只能通过 <strong>onChange</strong> 事件来操作，通过事件对象拿到最新value，赋值到到state上</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">import React, &#123; Component &#125; from &#x27;react&#x27;</span><br><span class="line"></span><br><span class="line">export class BrotherOne extends Component &#123;</span><br><span class="line">    constructor() &#123;</span><br><span class="line">        super()</span><br><span class="line">        this.state = &#123;</span><br><span class="line">            name: &quot;default&quot;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    changeInput(e) &#123;</span><br><span class="line">        console.log(e.target.value)</span><br><span class="line">        this.setState(&#123;</span><br><span class="line">            name: e.target.value</span><br><span class="line">        &#125;)</span><br><span class="line">        // 或 批量写法</span><br><span class="line">        this.setState(&#123;</span><br><span class="line">            [e.target.name]: e.target.value</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    render() &#123;</span><br><span class="line">        return (</span><br><span class="line">            &lt;div&gt;</span><br><span class="line">            	&lt;input value=&#123;this.state.name&#125; name=&#x27;name&#x27; onChange=&#123;e =&gt; this.changeInput(e)&#125; /&gt;</span><br><span class="line">                &#123;/* 非受控组件 */&#125;</span><br><span class="line">                &lt;input defaultValue=&#123;this.state.name&#125; /&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        )</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">export default BrotherOne</span><br></pre></td></tr></table></figure>

<h4 id="高阶组件（HOC）"><a href="#高阶组件（HOC）" class="headerlink" title="高阶组件（HOC）"></a>高阶组件（HOC）</h4><blockquote>
<p>  高阶函数：接收<strong>另外一个函数</strong>作为<strong>参数</strong> 或 <strong>返回一个函数</strong>作为<strong>返回值</strong> 的函数 </p>
<p>  高阶组件：本身就是一个函数，接收一个<strong>组件</strong>作为<strong>参数</strong> 并且 <strong>返回一个新的组件</strong>，在渲染之前<strong>拦截</strong>，处理到新组件后返回</p>
</blockquote>
<p>应用场景</p>
<ul>
<li><p>代替了<strong>Mixin</strong>混入</p>
</li>
<li><p>对组件注入数据 </p>
</li>
<li><p>封装隔代传值的Context</p>
</li>
<li><p><strong>memo</strong>就是一个高阶函数，性能优化也是通过高阶组件方式实现的</p>
</li>
<li><p>使用大量HOC，包裹太多层嵌套，也不好，然后出现了<strong>Hooks</strong></p>
</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">// 高阶组件,给使用的组件添加上 title</span><br><span class="line">export default function setTitle(WarpperComponent) &#123;</span><br><span class="line">    return function (props) &#123; // 函数组件中操作</span><br><span class="line">        console.log(&#123;...props&#125;); // 将父级本来就有的props 和 我们要新增的数据 一起传递给子组件将</span><br><span class="line">        return &lt;WarpperComponent &#123;...props&#125; title=&#x27;成功使用高阶组件 setTitle&#x27; /&gt;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">// 使用</span><br><span class="line">import React, &#123; PureComponent &#125; from &#x27;react&#x27;</span><br><span class="line">import setTitle from &#x27;./my-hoc/setTitle&#x27;</span><br><span class="line"></span><br><span class="line">export class App extends PureComponent &#123;</span><br><span class="line">    render() &#123;</span><br><span class="line">        const &#123; title &#125; = this.props;</span><br><span class="line">        return (</span><br><span class="line">            &lt;&gt;</span><br><span class="line">                &lt;div&gt;App - &#123;title&#125;&lt;/div&gt;</span><br><span class="line">            &lt;/&gt;</span><br><span class="line">        )</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">export default setTitle(App)</span><br></pre></td></tr></table></figure>



<h4 id="高阶应用"><a href="#高阶应用" class="headerlink" title="高阶应用"></a>高阶应用</h4><h5 id="createPortal-vue3-Teleport"><a href="#createPortal-vue3-Teleport" class="headerlink" title="createPortal (vue3 Teleport)"></a>createPortal (vue3 Teleport)</h5><blockquote>
<p>  <strong>createPortal</strong>：将React元素挂载到 root 外的其他位置</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">import &#123; createPortal &#125; from &#x27;react-dom&#x27;</span><br><span class="line"></span><br><span class="line">// jsx中</span><br><span class="line">export class CreatePortal extends PureComponent &#123;</span><br><span class="line">  render() &#123;</span><br><span class="line">    return (</span><br><span class="line">        createPortal(&lt;div&gt;createPortal&lt;/div&gt;,document.querySelector(&quot;#lzo&quot;)) </span><br><span class="line">        &#123;/* lzo元素必须提前存在 */&#125;</span><br><span class="line">    )</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="Fragment-vue3-Fragment"><a href="#Fragment-vue3-Fragment" class="headerlink" title="Fragment (vue3 Fragment)"></a>Fragment (vue3 Fragment)</h5><blockquote>
<p>  <strong>Fragment</strong>：包裹一段代码而不渲染到页面上，存在类<strong>似 key的属性</strong>无法使用</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">import &#123; Fragment &#125; from &quot;react&quot;;</span><br><span class="line"></span><br><span class="line">// jsx中</span><br><span class="line">rendel()&#123;</span><br><span class="line">    return (</span><br><span class="line">        &lt;Fragment&gt;</span><br><span class="line">            &lt;div&gt;</span><br><span class="line">                &lt;div&gt;下面是 Fragment 语法糖，&lt;/div&gt;</span><br><span class="line">                &lt;&gt;</span><br><span class="line">                &lt;/&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        &lt;/Fragment&gt;</span><br><span class="line">    )</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="Suspense"><a href="#Suspense" class="headerlink" title="Suspense"></a>Suspense</h5><blockquote>
<p>  异步加载未加载出来时，先使用fallback中的组件</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">const root = ReactDOM.createRoot(document.getElementById(&#x27;root&#x27;));</span><br><span class="line">root.render(</span><br><span class="line">    &lt;HashRouter&gt;</span><br><span class="line">        &lt;Suspense fallback=&#123;&lt;h3&gt;Loading...&lt;/h3&gt;&#125;&gt;</span><br><span class="line">            &lt;App /&gt;</span><br><span class="line">        &lt;/Suspense&gt;</span><br><span class="line">    &lt;/HashRouter&gt;</span><br><span class="line">);</span><br></pre></td></tr></table></figure>



<h5 id="StrictMode"><a href="#StrictMode" class="headerlink" title="StrictMode"></a>StrictMode</h5><blockquote>
<p>  StrictMode：仅在开发模式下生效的严格模式，也不会渲染到页面上</p>
</blockquote>
<p>检测范围，检测到报错提示</p>
<ul>
<li>识别不安全不推荐生命周期</li>
<li>废弃API</li>
<li>第一种过期的refs用法</li>
<li>检测一些意外副作用<ul>
<li><strong>开发环境</strong>中 <strong>constructor</strong>，<strong>生命周期</strong> 会被<strong>故意调用两次</strong>，查看你的代码执行多次时是否会产生一些问题（如事件没有移除）</li>
</ul>
</li>
</ul>
<h3 id="JSX"><a href="#JSX" class="headerlink" title="JSX"></a>JSX</h3><blockquote>
<p>  认识 JSX</p>
</blockquote>
<p>概念</p>
<ul>
<li>JSX 是一种 JavaScript 的语法扩展，或称为 <code>JavaScript XML</code></li>
<li>它用于描述<strong>UI界面 view,</strong> 并且<strong>完全</strong>可以和J<strong>avaScript融合在一起</strong></li>
<li>它不同于vue的模板语法，<strong>不需要</strong>专门学习模块语法中的<strong>一些指令</strong>（比如v-for，v-if）</li>
<li>React 认为 <strong>逻辑渲染</strong>本质上与其他<strong>UI逻辑</strong>存在很强的<strong>内在耦合</strong>（关联性强），所以选择 JSX<ul>
<li>UI 中绑定事件</li>
<li>展示数据状态</li>
<li>状态改变又要改变 UI</li>
</ul>
</li>
</ul>
<p>位置</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">render()&#123;</span><br><span class="line">    retrun (); // 这里面 或 放到这里使用的，就是jsx,运行会被bable转成js代码 </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>书写规范 <code>retrun () 中</code></p>
</blockquote>
<ul>
<li>只能有<strong>一个根元素</strong></li>
<li><strong>小括号</strong>，使 JSX 可以换行书写，方便阅读</li>
<li>单标签必须 <code>/&gt;</code>结尾</li>
</ul>
<h4 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h4><ul>
<li>作为子元素<code>&#123;&#125;</code>插入内容 <strong>Number</strong>、<strong>String</strong>、<strong>Array</strong> 可以直接显示，<strong>undefined</strong>、<strong>null</strong>、<strong>boll ** 不显示，</strong>Object对象** 不能直接插入</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br></pre></td><td class="code"><pre><span class="line">// 1.定义App根组件</span><br><span class="line">class App extends React.Component &#123;</span><br><span class="line">    constructor() &#123;</span><br><span class="line">        super();</span><br><span class="line">        this.state = &#123;</span><br><span class="line">            message:&#x27;note&#x27;,</span><br><span class="line">            count:0,</span><br><span class="line">            arr:[1,2,3,4],</span><br><span class="line">            isReady:true</span><br><span class="line">            </span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        this.btnClick = this.btnClick.bind(this);</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    btnClick()&#123;console.log(this)&#125;</span><br><span class="line">    btn2Click = ()=&gt; console.log(this);</span><br><span class="line">    btn3Click()&#123;console.log(this)&#125;;</span><br><span class="line">    btn4Click(event, name, age) &#123;console.log(event, name, age)&#125;</span><br><span class="line"></span><br><span class="line">    render() &#123;</span><br><span class="line">        const &#123;message,count,arr,isReady &#125; = this.state;</span><br><span class="line">        const countAdd = count + 1;</span><br><span class="line">        </span><br><span class="line">        let ele = null;</span><br><span class="line">        if(isReady)&#123;</span><br><span class="line">            ele = &lt;h1&gt;h1&lt;/h1&gt;</span><br><span class="line">        &#125;else&#123;</span><br><span class="line">            ele = &lt;h2&gt;h2&lt;/h2&gt;    </span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        return (</span><br><span class="line">            &#123; /* 注释 */ &#125;</span><br><span class="line">            &lt;div&gt;</span><br><span class="line">                &#123; /* 1、注释 */ &#125;</span><br><span class="line">                &#123; /* 2、插入内容变量 */ &#125;</span><br><span class="line">                &lt;h2&gt;&#123;message&#125;&lt;/h2&gt;</span><br><span class="line">                </span><br><span class="line">                &#123; /* 3、插入表达式 没有计算属性，可以直接通过js完成*/ &#125;</span><br><span class="line">                &lt;h2&gt;&#123;1+2&#125;&lt;/h2&gt;</span><br><span class="line">                &lt;h2&gt;&#123;countAdd&#125;&lt;/h2&gt;</span><br><span class="line">                </span><br><span class="line">                &#123; /* 4、调用方法 */ &#125;</span><br><span class="line">                &lt;ul&gt;&#123;arr.map(item=&gt; &lt;li&gt;&#123;item&#125;&lt;/li&gt;)&#125;&lt;/ul&gt; </span><br><span class="line">                &lt;ul&gt;&#123;this.getItem&#125;&lt;/ul&gt; </span><br><span class="line">                </span><br><span class="line">                &#123; /* 5、绑定属性 */ &#125;</span><br><span class="line">                &lt;img title=&#123;message&#125; src=&#123;xxx&#125;&gt;&lt;/img&gt;</span><br><span class="line">                &lt;h2 className=&quot;box&quot; &gt;绑定类&lt;/h2&gt; &#123; /* class 是关键字，bable解析可能会产生误解 */ &#125;</span><br><span class="line">				&lt;h2 className=&#123;`box1 box2 $&#123;countAdd==2?&#x27;box3&#x27;:&#x27;box4&#x27;&#125;`&#125; &gt;绑定类&lt;/h2&gt; </span><br><span class="line">                </span><br><span class="line">                &#123; /* 6、绑定样式 */ &#125;</span><br><span class="line">                 &lt;h2 style=&#123;&#123;color: &quot;red&quot;, fontSize: &quot;30px&quot;&#125;&#125;&gt;呵呵呵呵&lt;/h2&gt;</span><br><span class="line">                </span><br><span class="line">                &#123; /* 7、绑定事件 小驼峰*/ &#125;</span><br><span class="line">                 &lt;button onClick=&#123;this.btnClick&#125;&gt;修改文本&lt;/button&gt;</span><br><span class="line">                 &lt;button onClick=&#123;this.btn2Click&#125;&gt;按钮2&lt;/button&gt;</span><br><span class="line">                 &lt;button onClick=&#123;() =&gt; this.btn3Click()&#125;&gt;需要执行&lt;/button&gt; </span><br><span class="line">                 &lt;button onClick=&#123;(event) =&gt; this.btn4Click(event, &quot;why&quot;, 18)&#125;&gt;按钮4&lt;/button&gt;</span><br><span class="line">                </span><br><span class="line">                &#123; /* 8、条件渲染 js怎样就怎样 */ &#125;</span><br><span class="line">                &lt;div&gt;&#123;ele&#125;&lt;/div&gt;</span><br><span class="line">                &lt;div&gt;&#123; isReady?&lt;h1&gt;h1&lt;/h1&gt;:&lt;h2&gt;h2&lt;/h2&gt;  &#125;&lt;/div&gt;</span><br><span class="line">                &lt;div style=&#123;&#123;display:isReady ? &#x27;block&#x27;: &#x27;none&#x27;&#125;&#125;&gt;v-show &lt;/div&gt;</span><br><span class="line">                </span><br><span class="line">                &#123; /* 9、列表渲染 ，如果添加限制，向把arr处理一下再遍历 */ &#125;</span><br><span class="line">                &lt;div&gt;&#123;arr.map(item=&gt; &lt;div className=&#x27;item&#x27;&gt;item&lt;/div&gt;)&#125;&lt;/div&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    getItem()&#123;</span><br><span class="line">        &#123; /* 如果复杂的逻辑 */ &#125;</span><br><span class="line">        retrun this.state.arr.map(item=&gt; &lt;li&gt;&#123;item&#125;&lt;/li&gt;)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">const root = ReactDOM.createRoot(document.querySelector(&quot;#root&quot;));</span><br><span class="line">root.render(&lt;App /&gt;);</span><br></pre></td></tr></table></figure>

<blockquote>
<p>  Bable 解析 JSX </p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">&#123;/*</span><br><span class="line">	React.createElement(type,config,children)</span><br><span class="line">	</span><br><span class="line">	1、bable 将每一个 div 转换为 React.createElement(&quot;div&quot;,null,null)</span><br><span class="line">	通过 createElement 组成一个 JavaScript对象树，形成虚拟DOM</span><br><span class="line">	</span><br><span class="line">	2、再通过 document.createElement(&quot;dov&quot;) 转真实DOM</span><br><span class="line">	</span><br><span class="line">	有一个从 jsx -&gt; 虚拟DOM（js对象 ） -&gt; 真实DOM的过程 </span><br><span class="line">	  （jsx没有v-for，事件绑定这些，比较简单，bable可以直接解析，vue比较麻烦，template 通过v-loader来解析）</span><br><span class="line">	  </span><br><span class="line">	 虚拟DOM的好处</span><br><span class="line">	 	- 可以在家js中通过diff算法对比新旧虚拟dom，部分更新</span><br><span class="line">	 	- 动态判断是渲染成web端可以用的DOM结构，或渲染成其他各个平台认识的结构，实现跨平台</span><br><span class="line">	 	- 通过root.render 让虚拟DOM和真实DOM同步起来，这个过程叫做协调</span><br><span class="line">	 	- 只需要告诉react让ui展示什么状态，react去匹配，你不需要手动操作dom、属性、事件，实现声明式编程 </span><br><span class="line">*/&#125;</span><br><span class="line"></span><br><span class="line">return (</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">    	&lt;ul&gt;</span><br><span class="line">            &lt;li className=&#x27;item&#x27;&gt;Text&lt;/li&gt;</span><br><span class="line">            &lt;li className=&#x27;item&#x27;&gt;Text&lt;/li&gt;</span><br><span class="line">        &lt;/ul&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">// 转换后</span><br><span class="line">React.createElement(&quot;div&quot;,null,</span><br><span class="line">	React.createElement(&quot;ul&quot;,null,</span><br><span class="line">    	React.createElement(&quot;li&quot;,&#123;className:&#x27;item&#x27;&#125;,Text)</span><br><span class="line">    )</span><br><span class="line">)</span><br></pre></td></tr></table></figure>

<h3 id="过渡动画"><a href="#过渡动画" class="headerlink" title="过渡动画"></a>过渡动画</h3><blockquote>
<p>  React 社区维护的动画库 <code>react-transition-group</code></p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">// 1、需要额外安装  npm install react-transition-group -S</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * CSSTransition：常用这个来完成过度动画</span><br><span class="line"> *	  动画进入的三个阶段 </span><br><span class="line"> *        1、开始状态初始化 xxxx-enter   如 opacity:0</span><br><span class="line"> *        2、执行动画阶段 xxxx-enter-active    如 opacity:1</span><br><span class="line"> *        3、执行完成阶段 xxxx-enter-done </span><br><span class="line"> *    动画离开的三个阶段 </span><br><span class="line"> *        1、开始状态初始化 xxxx-exit         如 opacity:1</span><br><span class="line"> *        2、执行动画阶段 xxxx-exit-active    如 opacity:0</span><br><span class="line"> *        3、执行完成阶段 xxxx-exit-done </span><br><span class="line"> * SwitchTransition：两个组件显示和隐藏</span><br><span class="line"> * TransitionGroup：包裹多个动画组件，一般用于列表中元素动画</span><br><span class="line"> *</span><br><span class="line"> *</span><br><span class="line"> */</span><br></pre></td></tr></table></figure>

<h3 id="React-中的-CSS"><a href="#React-中的-CSS" class="headerlink" title="React 中的 CSS"></a>React 中的 CSS</h3><p>组件化的是<strong>局部的</strong>，而CSS的设<strong>计是全局</strong>的，所有组件化项目中，需要一个<strong>CSS的解决方案</strong></p>
<ol>
<li>编写局部CSS：让CSS具备自己的<strong>作用域</strong>，不会<strong>随意污染</strong>其他组件内的元素</li>
<li>编写动态CSS：获取当前组件的一些<strong>状态</strong>，<strong>根据不同的状态</strong> 来 <strong>生成不同的CSS</strong></li>
</ol>
<h4 id="常用编写方案"><a href="#常用编写方案" class="headerlink" title="常用编写方案"></a>常用编写方案</h4><h5 id="内联样式"><a href="#内联样式" class="headerlink" title="内联样式"></a>内联样式</h5><blockquote>
<p>  在jsx中通过style接收一个小驼峰命名属性的样式表对象，并且可以应用state中的状态来设置相关样式</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;h2 style=&#123;&#123;color: &quot;red&quot;, fontSize: `$&#123;titleSize&#125;px`&#125;&#125;&gt;呵呵呵呵&lt;/h2&gt;</span><br></pre></td></tr></table></figure>

<h5 id="普通css"><a href="#普通css" class="headerlink" title="普通css"></a>普通css</h5><blockquote>
<p>  编写普通css文件，通过 import “xx&#x2F;xx&#x2F;xx.css” 映入到组件，缺点：一个组件引入过，其他组件也会生效</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">import &#x27;./index.css&#x27;</span><br></pre></td></tr></table></figure>

<h5 id="CSS-modules"><a href="#CSS-modules" class="headerlink" title="CSS modules"></a>CSS modules</h5><blockquote>
<p>  CSS modules 并不是react特有的解决方案，而是<strong>webpack提供</strong>的，webpacd.config.js 中的 modules:true</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">import CssIndex from &#x27;./index.module.css&#x27; // 无论是css/scss/less 在正常名字上添加.module就可以</span><br><span class="line"></span><br><span class="line"> &lt;h2 className=&#123;CssIndex.title&#125;&gt;呵呵呵呵&lt;/h2&gt;</span><br><span class="line"></span><br><span class="line">/*</span><br><span class="line">	不能使用index-header 横杆写法</span><br><span class="line">	不方便动态修改</span><br><span class="line">*/</span><br></pre></td></tr></table></figure>

<h5 id="css-in-js"><a href="#css-in-js" class="headerlink" title="css in js"></a>css in js</h5><blockquote>
<p>  CSS 由 JavaScript 生成，而不是外部引入，由第三方库提供</p>
</blockquote>
<p>优点</p>
<ul>
<li>赋予CSS一些能力，样式嵌套、函数定义、逻辑复用动态修改</li>
<li>CSS预处理器功能类似，这个<strong>动态状态</strong>更方便</li>
<li>常见实现<code>css in js</code>库：<code>styled-components</code>、<code>emotion</code>、<code>glamorous</code></li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line">// 1、安装: npm install styled-components -S</span><br><span class="line"></span><br><span class="line">// 2、常见 style 组件</span><br><span class="line">import styled from &quot;styled-components&quot;</span><br><span class="line">import &#123; largeSize &#125; from &quot;./style/variables&quot; // 引入入全局变量,假设有 export const largeSize = &quot;18px&quot;</span><br><span class="line"></span><br><span class="line">// 2.1 标签模板字符串，调用styled的div方法，得到一个div组件</span><br><span class="line">// 2.2 可以接收外部传入的props</span><br><span class="line">// 2.3 styled.div.attrs(&#123;&#125;)``</span><br><span class="line">// 2.4 从变量文件导入全局的变量 largeSize ，并使用</span><br><span class="line">export const AppWrapper = styled.div` </span><br><span class="line">	.select&#123;</span><br><span class="line">		color:#f00;</span><br><span class="line">		font-size:$&#123;largeSize&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	.title&#123;</span><br><span class="line">		font-size:$&#123;props =&gt; props.size&#125;px;</span><br><span class="line">		.left&#123;</span><br><span class="line">			color:#f0f</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">`</span><br><span class="line"></span><br><span class="line">// 3、jsx 中使用</span><br><span class="line">import &#123; AppWarpper &#125; from &quot;./style&quot;</span><br><span class="line"></span><br><span class="line">class App extends React.Component &#123;</span><br><span class="line">    constructor() &#123;</span><br><span class="line">        super();</span><br><span class="line">        this.state = &#123;</span><br><span class="line">            size:30</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    render() &#123;</span><br><span class="line">        const &#123; size &#125; = this.state;</span><br><span class="line">        retrun(</span><br><span class="line">            &#123;/* div组件 会渲染成一个div标签，样式组件可以层层嵌套 */&#125;</span><br><span class="line">            &#123;/* 状态改变，样式自动更新 */&#125;</span><br><span class="line">            &lt;AppWarpper size=&#123;size&#125;&gt; </span><br><span class="line">                &lt;div className=&#x27;select&#x27;&gt;&lt;/div&gt;</span><br><span class="line">                &lt;div className=&#x27;title&#x27;&gt;</span><br><span class="line">                    &lt;div className=&#x27;left&#x27;&gt;&lt;/div&gt;</span><br><span class="line">                &lt;/div&gt;</span><br><span class="line">            &lt;/AppWarpper&gt;</span><br><span class="line">        )</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">// 4、vscode 安装 vscode-styled-components 插件高亮</span><br></pre></td></tr></table></figure>

<blockquote>
<p>  标签模板字符串，函数的其他调用方式</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">tagTmpStr</span>(<span class="params">...arg</span>)&#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(arg);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> num = <span class="number">10</span>;</span><br><span class="line"><span class="keyword">let</span> tag = <span class="string">&#x27;学习&#x27;</span></span><br><span class="line"><span class="title function_">tagTmpStr</span>(<span class="number">1</span>,<span class="number">2</span>);</span><br><span class="line">tagTmpStr<span class="string">`this is <span class="subst">$&#123;num&#125;</span> 个 <span class="subst">$&#123;tag&#125;</span>`</span>  <span class="comment">// [[&#x27;this is&#x27;,&#x27;个&#x27;,&#x27;&#x27;], 10, 学习]</span></span><br></pre></td></tr></table></figure>

<h4 id="classnames-动态添加类"><a href="#classnames-动态添加类" class="headerlink" title="classnames 动态添加类"></a>classnames 动态添加类</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">import classNames from &#x27;classnames&#x27;</span><br><span class="line"></span><br><span class="line">classNames(&#x27;foo&#x27;, &#x27;bar&#x27;); // =&gt; &#x27;foo bar&#x27;</span><br><span class="line">classNames(&#x27;foo&#x27;, &#123; bar: true &#125;); // =&gt; &#x27;foo bar&#x27;</span><br><span class="line">classNames(&#123; &#x27;foo-bar&#x27;: true &#125;); // =&gt; &#x27;foo-bar&#x27;</span><br><span class="line">classNames(&#x27;a&#x27;, [&#x27;b&#x27;, &#123; c: true, d: false &#125;]); // =&gt; &#x27;a b c&#x27;</span><br></pre></td></tr></table></figure>

<h3 id="Redux-状态管理"><a href="#Redux-状态管理" class="headerlink" title="Redux 状态管理"></a>Redux 状态管理</h3><blockquote>
<p>  纯函数</p>
</blockquote>
<p><strong>函数式编程</strong>非常重要的概念<strong>纯函数</strong>，<strong>组件</strong>、<strong>redux 的 reducer</strong> 也必须是纯函数</p>
<p><strong>纯函数：</strong></p>
<ul>
<li>相同的<strong>输入</strong>，得到的<strong>返回值一定相同</strong><ul>
<li>所有函数不能依赖外部变量</li>
</ul>
</li>
<li>函数内部的操作<strong>不能影响外部的数据</strong></li>
<li>优点：写纯函数的时候，<strong>只需要</strong>关心业务逻辑，<strong>不需要</strong>考虑<strong>传入的内容</strong>是怎么获得，或<strong>依赖的外部变量</strong>是否已经<strong>发生修改</strong></li>
</ul>
<blockquote>
<p>  作用</p>
</blockquote>
<p>Redux 就是帮助我们<strong>管理State的容器</strong>，Redux是 JavaScript的状态容器，提供了<strong>可预测的状态管理</strong>  </p>
<p>Redux 必须通过 <strong>派发（dispatch）action</strong>来<strong>更新数据</strong></p>
<blockquote>
<p>  三大原则</p>
</blockquote>
<p><strong>单一数据源</strong>：一般一个项目只创建一个store，方便state的<strong>维护、追踪、修改</strong></p>
<p><strong>State是只读的</strong>：唯一修改的方法是<strong>触发action</strong>，通过reducer产生，视图和网络请求也只能通过action描述自己想要修改的state，保证所有修改集中化处理，并按照严格书序来执行</p>
<p><strong>使用纯函数来执行修改</strong>：通过 reducer 将就的state，和新的action联系在一起，返回新的state</p>
<blockquote>
<p>  基础流程图</p>
</blockquote>
<p><img src= "" data-lazy-src="/../../../static/img/2022-12-28_080604.jpg"></p>
<h4 id="使用-1"><a href="#使用-1" class="headerlink" title="使用"></a>使用</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">// yarn add redux  //node 16.10.0 或 &gt;=18.0.0</span><br><span class="line"></span><br><span class="line">// 一般结构</span><br><span class="line">store/index.js</span><br><span class="line"></span><br><span class="line">store/reducer.js</span><br><span class="line"></span><br><span class="line">store/actionCreators.js</span><br><span class="line"></span><br><span class="line">store.constants.js</span><br></pre></td></tr></table></figure>



<h4 id="Action"><a href="#Action" class="headerlink" title="Action"></a>Action</h4><h4 id="Reducer"><a href="#Reducer" class="headerlink" title="Reducer"></a>Reducer</h4><blockquote>
<p>  reducer 是一个纯函数，作用是将传入的state和action结合起来生成一个新 的state</p>
</blockquote>
<h4 id="toolkit"><a href="#toolkit" class="headerlink" title="toolkit"></a>toolkit</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install @reduxjs/toolkit react-redux</span><br></pre></td></tr></table></figure>

<blockquote>
<p>  Toolkit 核心API</p>
</blockquote>
<ul>
<li><strong>configureStore</strong>：包装<code>createStore</code>，提供<strong>简化的配置选项</strong>和<strong>良好的默认值</strong> ，自动组合 <code>slice reducer</code>、添加任何<strong>Redux中间件</strong>、<code>redux-thunk</code>默认包含、启用<code>Redux DevTools Extension</code></li>
<li><strong>createSlice</strong>：接收reducer函数的对象、切片名称和初始状态。并自动生成reducer，并带有相应actions</li>
<li><strong>createAsyncThunk</strong>：异步数据操作</li>
</ul>
<h4 id="Redux-中间件如何实现"><a href="#Redux-中间件如何实现" class="headerlink" title="Redux 中间件如何实现"></a>Redux 中间件如何实现</h4><blockquote>
<p>  派发actions之前拦截，做一些事情（redux-thunk 拦截actions，判断内容是不是一个函数，如果是，就执行得到结果，再继续）</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">// 中间件原理，对每次派发的action进行拦截，打印日志案例</span><br><span class="line">export default function log(store)&#123;</span><br><span class="line">    // 保存我们 拦截操作前的 dispatch</span><br><span class="line">    const next = store.dispatch;</span><br><span class="line"></span><br><span class="line">    function logAndDispatch(action)&#123;</span><br><span class="line">        console.log(&#x27;派发前：&#x27;,action);</span><br><span class="line">        </span><br><span class="line">        // 操作完进行它原本的派发操作</span><br><span class="line">        next(action);</span><br><span class="line"></span><br><span class="line">        console.log(&#x27;派发后：&#x27;,store.getState());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    // Monkey Patching：猴补丁 =&gt; 篡改现有代码，对整体逻辑进行修改</span><br><span class="line">    // 任何地方执行dispatch 其实是执行 logAndDispatch</span><br><span class="line">    store.dispatch = logAndDispatch;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="开发中如何管理state好"><a href="#开发中如何管理state好" class="headerlink" title="开发中如何管理state好"></a>开发中如何管理state好</h4><ol>
<li>有些人，将所有状态放到redux，状态管理库中<strong>方便追踪和共享</strong></li>
<li>有些人，将某些组件<strong>自己的状态</strong>放到组件内部进行关联</li>
<li>建议组件ui相关的一些状态，或自己的状态放到组件内部管理，共享状态，包括请求的数据可以交给redux维护 </li>
<li>…具体情况具体评估</li>
</ol>
<h4 id="调试工具"><a href="#调试工具" class="headerlink" title="调试工具"></a>调试工具</h4><blockquote>
<p>  React Developer Tools</p>
</blockquote>
<blockquote>
<p>  Redux DevTools</p>
</blockquote>
<p>控制台 redux 数据默认是看不到的，建议开发环境开启，生产环境关闭</p>
<h3 id="React-Router-6-x"><a href="#React-Router-6-x" class="headerlink" title="React Router 6.x"></a>React Router 6.x</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install react-router-dom # react 社区维护</span><br></pre></td></tr></table></figure>

<blockquote>
<p>  基本使用</p>
</blockquote>
<ol>
<li>配置路由类型 <strong>BrowserRouter</strong> 和 <strong>HashRouter</strong></li>
</ol>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">// index.js </span><br><span class="line">import React from &#x27;react&#x27;;</span><br><span class="line">import ReactDOM from &#x27;react-dom/client&#x27;;</span><br><span class="line">import &#123; HashRouter &#125; from &#x27;react-router-dom&#x27;; // 使用配置 HashRouter</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">const root = ReactDOM.createRoot(document.getElementById(&#x27;root&#x27;));</span><br><span class="line">root.render(</span><br><span class="line">	&lt;HashRouter&gt;</span><br><span class="line">        &lt;App /&gt;</span><br><span class="line">    &lt;/HashRouter&gt;</span><br><span class="line">);</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<ol start="2">
<li>路由映射路径，与路由传参</li>
</ol>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line">import React, &#123; PureComponent &#125; from &#x27;react&#x27;</span><br><span class="line">import &#123; Link, NavLink, Navigate, Route, Routes &#125; from &#x27;react-router-dom&#x27;</span><br><span class="line">import Home from &#x27;./pages/Home&#x27;</span><br><span class="line">import About from &#x27;./pages/About&#x27;</span><br><span class="line">import Login from &#x27;./pages/Login&#x27;</span><br><span class="line">import NotFound from &#x27;./pages/NotFound&#x27;</span><br><span class="line">import HomeChild1 from &#x27;./pages/HomeChild1&#x27;</span><br><span class="line">import HomeChild2 from &#x27;./pages/HomeChild2&#x27;</span><br><span class="line"></span><br><span class="line">export class index extends PureComponent &#123;</span><br><span class="line">    // constructor() &#123;</span><br><span class="line">    //     super();</span><br><span class="line">    // &#125;</span><br><span class="line">    render() &#123;</span><br><span class="line">        return (</span><br><span class="line">            &lt;div&gt;</span><br><span class="line">                &lt;div&gt; </span><br><span class="line">                    &lt;div&gt;header&lt;/div&gt;</span><br><span class="line">                    &lt;div className=&#x27;nav&#x27;&gt;</span><br><span class="line">                        &#123;/* 1、不重要 */&#125;</span><br><span class="line">                        &lt;Link to=&quot;/home&quot;&gt;首页&lt;/Link&gt;</span><br><span class="line">                        &lt;Link to=&quot;/about&quot;&gt;关于&lt;/Link&gt;</span><br><span class="line">                        &lt;Link to=&quot;/login&quot;&gt;登陆&lt;/Link&gt;</span><br><span class="line"></span><br><span class="line">                        &#123;/* 2、不重要  激活自动添加 active 类,动态加style 和 className */&#125;</span><br><span class="line">                        &lt;NavLink to=&quot;/home&quot; style=&#123;(&#123; isActive &#125;) =&gt; (&#123; color: isActive ? &quot;#f00&quot; : &quot;&quot; &#125;)&#125;&gt;首页&lt;/NavLink&gt;</span><br><span class="line">                        &lt;NavLink to=&quot;/about&quot; style=&#123;(&#123; isActive &#125;) =&gt; (&#123; color: isActive ? &quot;#f00&quot; : &quot;&quot; &#125;)&#125;&gt;关于&lt;/NavLink&gt;</span><br><span class="line">                        &lt;NavLink to=&quot;/login&quot; style=&#123;(&#123; isActive &#125;) =&gt; (&#123; color: isActive ? &quot;#f00&quot; : &quot;&quot; &#125;)&#125;&gt;登陆&lt;/NavLink&gt;</span><br><span class="line"></span><br><span class="line">                        &#123;/* 3、Navigator 一出现，就会立刻跳转对应路径(配合逻辑判断使用) */&#125;</span><br><span class="line">                        &#123;/* &lt;div&gt;&#123;isToLogin ? &lt;Navigate to=&quot;/Login&quot; /&gt; : &quot;暂不跳转&quot;&#125;&lt;/div&gt; */&#125;</span><br><span class="line"></span><br><span class="line">                        &#123;/* 4、自己或通过js实现跳转 6.x版本类组件无法使用 hook useNavigate ,需要通过高阶组件*/&#125; </span><br><span class="line">                    &lt;/div&gt;</span><br><span class="line">                    &lt;hr /&gt;</span><br><span class="line">                &lt;/div&gt;</span><br><span class="line">                &lt;div className=&#x27;content&#x27;&gt;</span><br><span class="line">                    &#123;/* router2、映射关系表：path =&gt; Component */&#125;</span><br><span class="line"></span><br><span class="line">                    &lt;Routes&gt;</span><br><span class="line">                        &lt;Route path=&#x27;/&#x27; element=&#123;&lt;Navigate to=&quot;/home&quot; /&gt;&#125;&gt;&lt;/Route&gt;  </span><br><span class="line">                        &#123;/* 5.x  用 component 代替 element，还需要用属性 exact 精准匹配 */&#125;</span><br><span class="line">                        &lt;Route path=&#x27;/home&#x27; element=&#123;&lt;Home&gt;&lt;/Home&gt;&#125;&gt;</span><br><span class="line">                            &lt;Route path=&#x27;/home&#x27; element=&#123;&lt;Navigate to=&quot;/home/c1/456&quot; /&gt;&#125;&gt;&lt;/Route&gt;</span><br><span class="line">                            &#123;/*动态路由传参*/&#125;</span><br><span class="line">                            &lt;Route path=&#x27;/home/c1/:id&#x27; element=&#123;&lt;HomeChild1&gt;&lt;/HomeChild1&gt;&#125;&gt;&lt;/Route&gt; </span><br><span class="line">                            </span><br><span class="line">                            &#123;/*用于query传参*/&#125;</span><br><span class="line">                            &lt;Route path=&#x27;/home/c2&#x27; element=&#123;&lt;HomeChild2&gt;&lt;/HomeChild2&gt;&#125;&gt;&lt;/Route&gt; </span><br><span class="line">                        &lt;/Route&gt;</span><br><span class="line">                        &lt;Route path=&#x27;/about&#x27; element=&#123;&lt;About&gt;&lt;/About&gt;&#125;&gt;&lt;/Route&gt; </span><br><span class="line">                        &lt;Route path=&#x27;/login&#x27; element=&#123;&lt;Login&gt;&lt;/Login&gt;&#125;&gt;&lt;/Route&gt;</span><br><span class="line">                        &lt;Route path=&#x27;*&#x27; element=&#123;&lt;NotFound&gt;&lt;/NotFound&gt;&#125;&gt;&lt;/Route&gt;</span><br><span class="line">                    &lt;/Routes&gt;</span><br><span class="line"></span><br><span class="line">                &lt;/div&gt;</span><br><span class="line">                &lt;div&gt;footer&lt;/div&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        )</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">export default index</span><br></pre></td></tr></table></figure>

<ol start="3">
<li>封装高阶组件，时类组件也能用 react-router-dom 库提供的 hook</li>
</ol>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">// withRouter.js</span><br><span class="line">import &#123; useLocation, useNavigate, useParams, useSearchParams &#125; from &#x27;react-router-dom&#x27;</span><br><span class="line"></span><br><span class="line">// 高阶组件</span><br><span class="line">export default function withRouter(WarpperComponent) &#123;</span><br><span class="line">    return function (props) &#123;</span><br><span class="line">        // 导航跳转</span><br><span class="line">        const navigate = useNavigate();</span><br><span class="line"></span><br><span class="line">        // 获取动态路由参数</span><br><span class="line">        const params = useParams();</span><br><span class="line"></span><br><span class="line">        // 获取query参数(未解析)</span><br><span class="line">        const location = useLocation();</span><br><span class="line"></span><br><span class="line">        // 获取解析好的query参数 </span><br><span class="line">        const [searchParams] = useSearchParams() // 返回一个数组，数组里有一些方法</span><br><span class="line">        /**</span><br><span class="line">         *   URLSearchParams 接口定义了一些实用的方法来处理 URL 的查询字符串。</span><br><span class="line">         *      searchParams.get(&#x27;a&#x27;) 得到对象a属性的值</span><br><span class="line">         *      将 Object.fromEntries(searchParams.entries()) 数据转成对象</span><br><span class="line">         */</span><br><span class="line">        const query = Object.fromEntries(searchParams.entries());</span><br><span class="line"></span><br><span class="line">        const router = &#123; navigate, params, location, query &#125;;</span><br><span class="line">        return &lt;WarpperComponent &#123;...props&#125; router=&#123;router&#125; /&gt;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">// 使用</span><br><span class="line">import React, &#123; PureComponent &#125; from &#x27;react&#x27;</span><br><span class="line">import &#123; Link, Outlet &#125; from &#x27;react-router-dom&#x27;</span><br><span class="line">import &#123; withRouter &#125; from &#x27;../hoc&#x27;</span><br><span class="line">export class Home extends PureComponent &#123;</span><br><span class="line">    navigateTo(path) &#123;</span><br><span class="line">        let &#123; navigate &#125; = this.props.router; // useNavigate 类组件不能用，通过高阶函数返回函数组件，传递过来</span><br><span class="line">        navigate(path);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    render() &#123;</span><br><span class="line">        return (</span><br><span class="line">            &lt;div&gt;</span><br><span class="line">                &lt;div className=&#x27;home-header&#x27;&gt;</span><br><span class="line">                    &lt;Link to=&quot;/home/c1/123&quot;&gt;子路由1&lt;/Link&gt;</span><br><span class="line">                    &lt;Link to=&quot;/home/c2?a=1&amp;b=2&quot;&gt;子路由2&lt;/Link&gt;</span><br><span class="line">                    &lt;button onClick=&#123;e =&gt; this.navigateTo(&quot;/about&quot;)&#125;&gt;js跳转&lt;/button&gt;</span><br><span class="line">                &lt;/div&gt;</span><br><span class="line">                &lt;div className=&#x27;home-centert&#x27;&gt;</span><br><span class="line">                    &#123;/* 占位组件 类似vue的 router-view */&#125;</span><br><span class="line">                    &lt;Outlet&gt;&lt;/Outlet&gt;</span><br><span class="line">                &lt;/div&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        )</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">export default withRouter(Home)</span><br></pre></td></tr></table></figure>

<ol start="3">
<li>路由配置</li>
</ol>
<pre><code> 1.   router5.x 需要安装**react-router-config**才能提取单独配置文件，6.x 直接就能用
</code></pre>
<h3 id="React-Hooks"><a href="#React-Hooks" class="headerlink" title="React Hooks"></a>React Hooks</h3><blockquote>
<p>  hook ( hook into ) 钩入，意思是可以从其他地方，将保存好的状态钩入进来（如useState钩入状态）</p>
</blockquote>
<ol>
<li>Hook解决了<strong>类组件复杂的</strong>的问题，弥补了 <strong>函数组件</strong>一些不足的地方</li>
<li>可以在不编写class的情况下使用state状态管理，什么周期以及其他React特性</li>
<li>是否使用Hook是可选的，完全向下兼容，不需要将旧代码重构成hook</li>
</ol>
<blockquote>
<p>  注意事项</p>
</blockquote>
<ol>
<li>Hook能在<strong>函数组件</strong>中，并且是<strong>最外顶层</strong>使用，不能在<strong>类组件</strong> 或者 <strong>函数组件之外的地方</strong>使用</li>
<li>Hook也能在自定义hook中使用（React中必须是  useXxx 格式的函数名）</li>
</ol>
<h4 id="useState"><a href="#useState" class="headerlink" title="useState"></a>useState</h4><blockquote>
<p>  设置与获取函数组件状态，从react中导入，是一个hook</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">import React, &#123; useState &#125; from &#x27;react&#x27;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> *  useState</span><br><span class="line"> *      参数：只有一个参数，初始化值，不设置位undefined</span><br><span class="line"> *      返回值：数组，包含两个元素 [状态单前值，设置值的函数]</span><br><span class="line"> *      作用和 类组件的 this.state 是</span><br><span class="line"> *   </span><br><span class="line"> *  点击button后做两件事情，通过 setCounter 重新设置值，同时将新的值返回过来，渲染到页面上</span><br><span class="line"> */</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">function CountHook() &#123;</span><br><span class="line">    const [counter, setCounter] = useState(0); // 首次 counter 变量 默认为0</span><br><span class="line">    return (</span><br><span class="line">        &lt;div&gt;</span><br><span class="line">            &lt;div&gt;</span><br><span class="line">                counterVal: &#123;counter&#125;</span><br><span class="line">                &lt;button onClick=&#123;e =&gt; setCounter(counter + 1)&#125;&gt;+1&lt;/button&gt;</span><br><span class="line">                &lt;button onClick=&#123;e =&gt; setCounter(counter - 1)&#125;&gt;-1&lt;/button&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">    )</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">export default CountHook</span><br></pre></td></tr></table></figure>

<h4 id="useEffect"><a href="#useEffect" class="headerlink" title="useEffect"></a>useEffect</h4><blockquote>
<p>  由于生命周期中某阶段<strong>网路请求</strong>、<strong>手动更新DOM</strong>、<strong>事件监听</strong>，都是<strong>React更新DOM</strong>的<strong>副作用</strong>（Dide Effects）</p>
</blockquote>
<blockquote>
<p>  所有完成这些功能的Hook 官方称为 Effect Hook</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">// useEffect 主要是为了处理 以前生命周期的很多逻辑</span><br><span class="line">useEffect(() =&gt; &#123;</span><br><span class="line">    // 当前回调函数绘制组件被渲染完成后，自动执行 （网络请求、DOM操作、事件监听）</span><br><span class="line">    document.title = counter;</span><br><span class="line"></span><br><span class="line">    // 返回值，需要返回一个回调函数 ==&gt; 组件被重新渲染，或者组件被卸载的时候执行</span><br><span class="line">    return () =&gt; &#123; </span><br><span class="line">        // 清除机制，做一些取消定时器，销毁的操作</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">useEffect(() =&gt; &#123;&#125;)  // 可以多个 按顺序执行</span><br></pre></td></tr></table></figure>

<blockquote>
<p>  每次渲染组件，默认情况下都会走 effect，所以需要 effect 性能优化</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">// 参数二 ，第二次渲染是，只有在数组中的状态发生改变，才会再次执行 回调(空数组说明，永远不会再次执行了)</span><br><span class="line">useEffect(()=&gt;&#123;</span><br><span class="line">    console.log(&#x27;只执行一次，发生网络请求&#x27;)</span><br><span class="line">    return () =&gt; &#123; </span><br><span class="line">        console.log(&#x27;只有组件被卸载才会执行&#x27;)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;,[])</span><br><span class="line">useEffect(()=&gt;&#123;</span><br><span class="line">    console.log(&#x27;counter 发生变化就会执行&#x27;)</span><br><span class="line">&#125;,[counter]) // 有点像vue watch的 监听counter,状态发生改变就做一些事情</span><br></pre></td></tr></table></figure>

<h4 id="特殊场景使用的hook"><a href="#特殊场景使用的hook" class="headerlink" title="特殊场景使用的hook"></a>特殊场景使用的hook</h4><blockquote>
<p>  useContext (子子孙孙传参)</p>
</blockquote>
<blockquote>
<p>  useImperativeHandle(作用子组件暴露一些方法，给父组件通过ref使用)</p>
</blockquote>
<blockquote>
<p>  useLayoutEffect ( <strong>useEffect</strong> 组件<strong>渲染完成</strong>之后执行里面，这个是在渲染DOM更新之前（阻塞），先做一些事情，再更新DOM)</p>
</blockquote>
<h4 id="性能优化hook"><a href="#性能优化hook" class="headerlink" title="性能优化hook"></a>性能优化hook</h4><blockquote>
<p>  useRef（总是返回同一个对象，操作dom）、useCallback 和 useMemo</p>
</blockquote>
<h4 id="自定义hook"><a href="#自定义hook" class="headerlink" title="自定义hook"></a>自定义hook</h4><blockquote>
<p>  本质上只是<strong>函数代码逻辑的抽取</strong></p>
</blockquote>
<h4 id="React18-新增-hook"><a href="#React18-新增-hook" class="headerlink" title="React18 新增 hook"></a>React18 新增 hook</h4><blockquote>
<p>  useId （只有早SSR同构应用中使用，生成横跨客户端和服务端的唯一ID,并且避免 hydration 不匹配的问题）</p>
</blockquote>
<blockquote>
<p>  useTransition （）</p>
</blockquote>
<h4 id="redux-hook"><a href="#redux-hook" class="headerlink" title="redux hook"></a>redux hook</h4><blockquote>
<p>  以前必须通过 react-redux 的 connect 编写 mapStateToProps 和 mapDispatchToProps 管理 react 和 redux</p>
</blockquote>
<h5 id="useSelector"><a href="#useSelector" class="headerlink" title="useSelector"></a>useSelector</h5><blockquote>
<p>  可以将 state 映射到组件中</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">// useSelector 代替 mapStateToProps</span><br><span class="line">// 默认情况下useSelect监听的是整个state，当某个组件状态发生改变时，所有使用useSelector的子组件都会重新渲染</span><br><span class="line">const &#123; homename, banners &#125; = useSelector((state) =&gt; &#123;</span><br><span class="line">    return &#123;</span><br><span class="line">        homename: state.home.homename,</span><br><span class="line">        banners: state.home.banners</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">// shallowEqual 比较数据是否发生改变，不受其他组件状态变化影响，比较自己的状态如果没变化，就不需要重新渲染</span><br><span class="line">const &#123; homename, banners &#125; = useSelector((state) =&gt; &#123;</span><br><span class="line">    return &#123;</span><br><span class="line">        homename: state.home.homename,</span><br><span class="line">        banners: state.home.banners</span><br><span class="line">    &#125;</span><br><span class="line">&#125;,shallowEqual)</span><br></pre></td></tr></table></figure>

<h5 id="useDispatch"><a href="#useDispatch" class="headerlink" title="useDispatch"></a>useDispatch</h5><blockquote>
<p>  直接获取dispatch函数</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">// useDispatch 代替 mapDispatchToProps</span><br><span class="line">const dispatch = useDispatch();</span><br><span class="line"></span><br><span class="line">function view_change_name(name) &#123;</span><br><span class="line">    dispatch(changeHomeNameAction(name))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="React-ClI"><a href="#React-ClI" class="headerlink" title="React ClI"></a>React ClI</h3><blockquote>
<p>  建筑学的概念，表示搭建建筑物时，<strong>临时搭建</strong>出来的<strong>一个框架</strong>，处理里一些问题，</p>
</blockquote>
<ul>
<li>目录机构组织</li>
<li>管理文件直接的相互依赖</li>
<li>管理第三方依赖</li>
<li>发布前的压缩打包。。。</li>
<li>浏览器不认识的代码转换</li>
<li>所有webpack相关的都存到 <code>react-scripts</code> 中了，<code>执行 npm run </code>就可以弹出，就能看到了，<strong>不可逆</strong></li>
</ul>
<blockquote>
<p>  PWA</p>
</blockquote>
<ul>
<li><code>Progressive Web App</code> 渐进式WEB应用</li>
<li>首先是一个<strong>网页</strong>，通过<strong>Web技术编写</strong>出一个<strong>网页应用</strong></li>
<li>随后添加<strong>App Manifest</strong> 和 <strong>Service Worker</strong> 来实现<strong>安装和离线缓存</strong>等功能 <ul>
<li>App Manifest：手机上某些浏览器（如Google）右上角更多里面，将页面添加到桌面，看上去就跟app差不多</li>
<li>Service Worker：当没网的时候打开这个Web App，还能看到上一次浏览的一些东西</li>
</ul>
</li>
<li>这种Web存在的形式 称为 <strong>Web App</strong></li>
<li>作用: 添加到<strong>主屏幕</strong>、<strong>离线缓存</strong>、<strong>消息推送</strong>等 一系列NativeApp的相关功能</li>
</ul>
<h4 id="create-react-app-CRA"><a href="#create-react-app-CRA" class="headerlink" title="create-react-app(CRA)"></a>create-react-app(CRA)</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">1、全局安装 npm install create-react-app -g</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">2、创建 create-react-app &lt;object-name&gt;    - 不允许存在大写字母</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">3、 <span class="built_in">cd</span>   yarn start</span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">目录结构</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">    public 一些静态文件</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">        index.html、favicon.ico 入口文件，标题图标</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">        两个logo.png、manifest.json 都是配置 PWA的一些资源样式配置</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">        robots.txt 告诉搜索引擎哪些东西可以被爬虫爬</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">    src  源码</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"> </span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">eject 后多出</span>     </span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">    config</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">    scripts</span></span><br></pre></td></tr></table></figure>

<h3 id="SSR"><a href="#SSR" class="headerlink" title="SSR"></a>SSR</h3><blockquote>
<p>  服务端渲染，Vue&#x2F;React   &#x3D;&gt; nuxt&#x2F;next</p>
</blockquote>
<p>xxx &#x3D;&gt; 前后端分离 &#x3D;&gt; SPA:单页面富应用 </p>
<p>SPA应用存在的问题</p>
<p>1、首屏的渲染速度</p>
<p>早期SSR页面(JSP 那种)，在服务器将整个网站都渲染好，请求的时候拿到的就是完整的页面，有利于SEO优化</p>
<p>SPA页面: 加载页面 –&gt;下载页面中引入的bundle.js –&gt; 浏览器执行下载的代码 –&gt; 执行完成才能渲染处理 ，导致速度慢</p>
<p>2、SEO优化问题</p>
<p>当页面应用的数据都是通过js文件生成的，搜索引擎收入的只有index.html页面 ，只有数据顶级挂载点，和一些基础信息，SPA网站的内容是爬取不到的，所有被匹配到的东西很少，导致排名很靠后</p>
<blockquote>
<p>  SSR 解决了 SPA 的这些问题</p>
</blockquote>
<p>借助node生成html页面，浏览器直接显示，浏览器不需要下载执行的步骤了 </p>
<blockquote>
<p>  实现步骤</p>
</blockquote>
<ul>
<li><p>SSR同构应用(可以运行在服务器，也能运行在客户端)</p>
<pre><code>    -	在服务器获取网络资源，生成dom字符串（无法交互）

    -	客户端也会运行一次，将交互的操作匹配到服务器生成的dom字符串中（**hydration**）
</code></pre>
</li>
</ul>
<h3 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h3><blockquote>
<p>  sass 直接 <code>npm i sass</code> 安装就能使用</p>
</blockquote>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="http://example.com">lzoxun</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="http://example.com/2023/07/22/web/react/react-docs/">http://example.com/2023/07/22/web/react/react-docs/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="http://example.com" target="_blank">学习笔记</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"></div><div class="post_share"><div class="social-share" data-image="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/js/social-share.min.js" defer></script></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/2023/07/22/web/style/style-grid/" title="grid网格布局"><div class="cover" style="background: var(--default-bg-color)"></div><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">grid网格布局</div></div></a></div><div class="next-post pull-right"><a href="/2023/07/22/web/threejs/base/" title="Three-基础"><div class="cover" style="background: var(--default-bg-color)"></div><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">Three-基础</div></div></a></div></nav></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src= "" data-lazy-src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">lzoxun</div><div class="author-info__description"></div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">108</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">1</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/liaozhongxun"><i class="fab fa-github"></i><span>Follow Me</span></a><div class="card-info-social-icons is-center"><a class="social-icon" href="https://github.com/liaozhongxun" target="_blank" title="Github"><i class="fab fa-github" style="color: #24292e;"></i></a><a class="social-icon" href="mailto:869664233@gmail.com" target="_blank" title="Email"><i class="fas fa-envelope" style="color: #4a7dbe;"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">这是我的文档</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%AE%80%E4%BB%8B"><span class="toc-number">1.</span> <span class="toc-text">简介</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%BC%80%E5%8F%91%E4%BE%9D%E8%B5%96"><span class="toc-number">1.1.</span> <span class="toc-text">开发依赖</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%AF%B9%E6%AF%94vue"><span class="toc-number">1.2.</span> <span class="toc-text">对比vue</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%BB%84%E4%BB%B6"><span class="toc-number">2.</span> <span class="toc-text">组件</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%B1%BB%E7%BB%84%E4%BB%B6-rpce"><span class="toc-number">2.1.</span> <span class="toc-text">类组件 rpce</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F"><span class="toc-number">2.1.1.</span> <span class="toc-text">生命周期</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%87%BD%E6%95%B0%E7%BB%84%E4%BB%B6-rfce%EF%BC%8Crmc"><span class="toc-number">2.2.</span> <span class="toc-text">函数组件  rfce，rmc</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%BB%84%E4%BB%B6%E9%80%9A%E4%BF%A1"><span class="toc-number">2.3.</span> <span class="toc-text">组件通信</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E7%88%B6%E5%AD%90%E9%80%9A%E4%BF%A1%EF%BC%88props-%E7%94%B1%E7%88%B6%E5%88%B0%E5%AD%90%EF%BC%89"><span class="toc-number">2.3.1.</span> <span class="toc-text">父子通信（props 由父到子）</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E9%9D%9E%E7%88%B6%E5%AD%90%E9%9A%94%E5%B1%82%E9%80%9A%E4%BF%A1"><span class="toc-number">2.3.2.</span> <span class="toc-text">非父子隔层通信</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#setState-%E8%AF%A6%E7%BB%86%E4%BD%BF%E7%94%A8"><span class="toc-number">2.4.</span> <span class="toc-text">setState 详细使用</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BC%98%E5%8C%96"><span class="toc-number">2.5.</span> <span class="toc-text">优化</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%9B%B4%E6%96%B0%E6%9C%BA%E5%88%B6"><span class="toc-number">2.5.1.</span> <span class="toc-text">更新机制</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#shouldComponentUpdate-%EF%BC%88SCU%EF%BC%89"><span class="toc-number">2.5.2.</span> <span class="toc-text">shouldComponentUpdate （SCU）</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#React-Refs-%E8%8E%B7%E5%8F%96-dom"><span class="toc-number">2.5.3.</span> <span class="toc-text">React Refs 获取 dom</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%8F%97%E6%8E%A7%E7%BB%84%E4%BB%B6%E4%B8%8E%E9%9D%9E%E5%8F%97%E6%8E%A7%E7%BB%84%E4%BB%B6"><span class="toc-number">2.5.4.</span> <span class="toc-text">受控组件与非受控组件</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%AB%98%E9%98%B6%E7%BB%84%E4%BB%B6%EF%BC%88HOC%EF%BC%89"><span class="toc-number">2.6.</span> <span class="toc-text">高阶组件（HOC）</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%AB%98%E9%98%B6%E5%BA%94%E7%94%A8"><span class="toc-number">2.7.</span> <span class="toc-text">高阶应用</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#createPortal-vue3-Teleport"><span class="toc-number">2.7.1.</span> <span class="toc-text">createPortal (vue3 Teleport)</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#Fragment-vue3-Fragment"><span class="toc-number">2.7.2.</span> <span class="toc-text">Fragment (vue3 Fragment)</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#Suspense"><span class="toc-number">2.7.3.</span> <span class="toc-text">Suspense</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#StrictMode"><span class="toc-number">2.7.4.</span> <span class="toc-text">StrictMode</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#JSX"><span class="toc-number">3.</span> <span class="toc-text">JSX</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8"><span class="toc-number">3.1.</span> <span class="toc-text">使用</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%BF%87%E6%B8%A1%E5%8A%A8%E7%94%BB"><span class="toc-number">4.</span> <span class="toc-text">过渡动画</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#React-%E4%B8%AD%E7%9A%84-CSS"><span class="toc-number">5.</span> <span class="toc-text">React 中的 CSS</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%B8%B8%E7%94%A8%E7%BC%96%E5%86%99%E6%96%B9%E6%A1%88"><span class="toc-number">5.1.</span> <span class="toc-text">常用编写方案</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%86%85%E8%81%94%E6%A0%B7%E5%BC%8F"><span class="toc-number">5.1.1.</span> <span class="toc-text">内联样式</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%99%AE%E9%80%9Acss"><span class="toc-number">5.1.2.</span> <span class="toc-text">普通css</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#CSS-modules"><span class="toc-number">5.1.3.</span> <span class="toc-text">CSS modules</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#css-in-js"><span class="toc-number">5.1.4.</span> <span class="toc-text">css in js</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#classnames-%E5%8A%A8%E6%80%81%E6%B7%BB%E5%8A%A0%E7%B1%BB"><span class="toc-number">5.2.</span> <span class="toc-text">classnames 动态添加类</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Redux-%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86"><span class="toc-number">6.</span> <span class="toc-text">Redux 状态管理</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8-1"><span class="toc-number">6.1.</span> <span class="toc-text">使用</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Action"><span class="toc-number">6.2.</span> <span class="toc-text">Action</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Reducer"><span class="toc-number">6.3.</span> <span class="toc-text">Reducer</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#toolkit"><span class="toc-number">6.4.</span> <span class="toc-text">toolkit</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Redux-%E4%B8%AD%E9%97%B4%E4%BB%B6%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0"><span class="toc-number">6.5.</span> <span class="toc-text">Redux 中间件如何实现</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%BC%80%E5%8F%91%E4%B8%AD%E5%A6%82%E4%BD%95%E7%AE%A1%E7%90%86state%E5%A5%BD"><span class="toc-number">6.6.</span> <span class="toc-text">开发中如何管理state好</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%B0%83%E8%AF%95%E5%B7%A5%E5%85%B7"><span class="toc-number">6.7.</span> <span class="toc-text">调试工具</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#React-Router-6-x"><span class="toc-number">7.</span> <span class="toc-text">React Router 6.x</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#React-Hooks"><span class="toc-number">8.</span> <span class="toc-text">React Hooks</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#useState"><span class="toc-number">8.1.</span> <span class="toc-text">useState</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#useEffect"><span class="toc-number">8.2.</span> <span class="toc-text">useEffect</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%89%B9%E6%AE%8A%E5%9C%BA%E6%99%AF%E4%BD%BF%E7%94%A8%E7%9A%84hook"><span class="toc-number">8.3.</span> <span class="toc-text">特殊场景使用的hook</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96hook"><span class="toc-number">8.4.</span> <span class="toc-text">性能优化hook</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%87%AA%E5%AE%9A%E4%B9%89hook"><span class="toc-number">8.5.</span> <span class="toc-text">自定义hook</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#React18-%E6%96%B0%E5%A2%9E-hook"><span class="toc-number">8.6.</span> <span class="toc-text">React18 新增 hook</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#redux-hook"><span class="toc-number">8.7.</span> <span class="toc-text">redux hook</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#useSelector"><span class="toc-number">8.7.1.</span> <span class="toc-text">useSelector</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#useDispatch"><span class="toc-number">8.7.2.</span> <span class="toc-text">useDispatch</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#React-ClI"><span class="toc-number">9.</span> <span class="toc-text">React ClI</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#create-react-app-CRA"><span class="toc-number">9.1.</span> <span class="toc-text">create-react-app(CRA)</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#SSR"><span class="toc-number">10.</span> <span class="toc-text">SSR</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%85%8D%E7%BD%AE"><span class="toc-number">11.</span> <span class="toc-text">配置</span></a></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2023/07/22/window/win-11/" title="win 11 set">win 11 set</a><time datetime="2023-07-22T07:14:09.700Z" title="发表于 2023-07-22 15:14:09">2023-07-22</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2023/07/22/window/win-gitbash/" title="git bash">git bash</a><time datetime="2023-07-22T07:14:09.700Z" title="发表于 2023-07-22 15:14:09">2023-07-22</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2023/07/22/window/win-wsl/" title="wsl">wsl</a><time datetime="2023-07-22T07:14:09.700Z" title="发表于 2023-07-22 15:14:09">2023-07-22</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2023/07/22/window/win-main/" title="window">window</a><time datetime="2023-07-22T07:14:09.700Z" title="发表于 2023-07-22 15:14:09">2023-07-22</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2023/07/22/web/%E5%85%BC%E5%AE%B9%E9%97%AE%E9%A2%98/" title="兼容问题">兼容问题</a><time datetime="2023-07-22T07:14:09.699Z" title="发表于 2023-07-22 15:14:09">2023-07-22</time></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">&copy;2020 - 2023 By lzoxun</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="translateLink" type="button" title="简繁转换">繁</button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="/js/tw_cn.js"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox/fancybox.umd.min.js"></script><script src="https://cdn.jsdelivr.net/npm/instant.page/instantpage.min.js" type="module"></script><script src="https://cdn.jsdelivr.net/npm/vanilla-lazyload/dist/lazyload.iife.min.js"></script><script src="https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.js"></script><script>function panguFn () {
  if (typeof pangu === 'object') pangu.autoSpacingPage()
  else {
    getScript('https://cdn.jsdelivr.net/npm/pangu/dist/browser/pangu.min.js')
      .then(() => {
        pangu.autoSpacingPage()
      })
  }
}

function panguInit () {
  if (false){
    GLOBAL_CONFIG_SITE.isPost && panguFn()
  } else {
    panguFn()
  }
}

document.addEventListener('DOMContentLoaded', panguInit)</script><div class="js-pjax"></div><script id="canvas_nest" defer="defer" color="0,0,255" opacity="0.7" zIndex="-1" count="99" mobile="false" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/dist/canvas-nest.min.js"></script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><div id="local-search"><div class="search-dialog"><nav class="search-nav"><span class="search-dialog-title">搜索</span><span id="loading-status"></span><button class="search-close-button"><i class="fas fa-times"></i></button></nav><div class="is-center" id="loading-database"><i class="fas fa-spinner fa-pulse"></i><span>  数据库加载中</span></div><div class="search-wrap"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章" type="text"/></div></div><hr/><div class="no-result" id="local-search-results"></div><div id="local-search-stats-wrap"></div></div></div><div id="search-mask"></div><script src="/js/search/local-search.js"></script></div></div><script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"log":false,"model":{"jsonPath":"/live2dw/assets/haruto.model.json"},"display":{"position":"right","width":100,"height":200,"right":300},"mobile":{"show":true}});</script></body></html>